Repository navigation
feat(SnapshotKit): support measured Duo capture geometry - #377
Conversation
61518f9 to
8d09084
Compare
02f3c09 to
ca5dede
Compare
ca5dede to
b4f5f88
Compare
There was a problem hiding this comment.
Do we need to keep this committed, or can we remove it now that we have the measurements?
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Removed in 9f9fa8457. No production code or tests consumed the raw JSON. The README retains the measurement date, runtime and Xcode builds, collection method, hardware-verification caveat, and pending native 27.2 validation. Preset values are unchanged, and the original measurements remain in Git history. Updated the source pointer and measurement guidance, and propagated the cleanup through the stack.
b4f5f88 to
1a7d8ae
Compare
| public var resolvedLayoutTraits: Frame.LayoutTraits? { | ||
| guard let layoutTraits else { return device.layoutTraits } | ||
| return Frame.LayoutTraits( | ||
| horizontalSizeClass: layoutTraits.horizontalSizeClass == .compact ? .compact : .regular, |
There was a problem hiding this comment.
Please change these (and others) to actual switch statements so they fail if we add new cases.
There was a problem hiding this comment.
(Either that, or add an extension to layoutTraits.verticalSizeClass that switches internally to convert to the value in question, and then call that.)
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Fixed in 42ab5b40e. Both axes now use one conversion property with an exhaustive switch; idiom conversion also switches explicitly over every case. No default or ternary fallback remains in these mappings, so adding a case requires an explicit conversion.
All 56 SnapshotKit tests passed. All six Developer Overlay captures matched their existing references byte for byte; architecture and formatting checks passed. Propagated through #378 and #372.
…layout propagation
1a7d8ae to
9e759fc
Compare
There was a problem hiding this comment.
The color changes here seem somewhat suspect
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Fixed in f05ca6240. The color shift was a capture defect: detaching the window scene produced bright bands, ripples, and a hard cutoff in the native glass. These Developer Overlay fixtures now opt into scene retention; the product's colors and material styling are unchanged.
The three menu references were refreshed after visual review. All six overlay captures then repeated byte for byte at this PR's layer. The adaptive layer also passed all six after accounting for its additional Duo Layout Lab row and content bounds.
Full-resolution before/after images are also in the updated PR description. Full CI is running on the published head.
Move generic accessibility capture fixes and reviewed references into the renderer layer. Measure Timeline rows eagerly, settle Settings sizing, and retain the scene for Developer Overlay glass. Preserve layer-specific navigation and accessibility semantics. Validation: 2,922 iOS unit tests, then 679 affected WhereUI tests; 71 snapshot tests covered by the full run and focused assertions; all six overlay captures repeat byte-for-byte. Architecture, host checks, and SwiftFormat pass.
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Developer Overlay — light iPhone full-content fixture at f05ca6240. The snapshot retains its window scene so native glass stays uniform; menu styling is unchanged. All six overlay captures repeated byte for byte. Capture defect and fix discussion.
Remove the unused raw simulator record. Keep the measurement date, toolchain, collection method, and outstanding native validation in the module README; preserve all preset values. Update the measurement rule and source pointer.
Share a switch-based size-class conversion between both axes and switch explicitly over the configuration idiom. Adding an enum case now requires a deliberate frame mapping instead of falling through a ternary. Existing mappings and identifiers are unchanged. Validation: all 56 SnapshotKit tests, architecture checks, and SwiftFormat pass.

Summary
Add explicit frame layout traits and recorded Duo profiles to the Xcode 27.2 baseline from main. Apply requested content clearance after UIKit finalizes containment and native geometry.
This layer retains the existing Where navigation. Its image references establish the new capture baseline before the adaptive app changes. Calendar month sections, day rows, and Timeline rows measure eagerly so full-content captures include the final rows; the selection and tabletop changes remain in the app PR. Eager Timeline measurement removes blank tails caused by lazy height estimates in a bottom-anchored scroll view. Settings waits for native search chrome to settle before measuring its full height. Existing scrolling onboarding and Devices fixtures use full-content frames. Theme choices also fall back to a vertical layout when narrow, and large-text Logged Days rows retain their dates, notes, and labels.
Screenshots
Developer Overlay, light iPhone full-content capture. Retaining the scene restores uniform native glass without changing the menu's styling, dimensions, or content.
Before:
9e759fc8. After:f05ca6240; all six overlay captures reproduced byte for byte.Primary APIs
SnapshotConfiguration.Frame.LayoutTraitsowns horizontal and vertical size classes and interface idiom. Configuration-level layout traits remain supported and take precedence over frame defaults. Phone and iPad presets carry truthful traits without changing their filenames.Frame.scenePolicycontrols capture scene retention without renaming references. Both configured assertions and hosted PNG export honor it.Frame.viewportcaptures bounded shell composition. It must be paired with full-content captures of scrolling panes..narrowWindowcovers a synthetic multitasking container.Previews and UIKit capture use the same mapping. Conversion from configuration traits to frame traits uses exhaustive switches for both size classes and idiom, so new enum cases require an explicit mapping. Custom frames can supply
layoutTraits; component frames inherit the host's traits.Capture and tooling boundaries
All capture entry points acquire one lock before host discovery, validation, and preparation. Fixed, regular-width phone captures retain their scene so native bar geometry stays stable. Other synthetic captures detach the marked window by default, preserving compact title space and anchoring full-content search to expanded content. Capture and measurement hosts reconcile their effective insets after containment and layout, with another reconciliation after settling. The predicate uses content-controller traits, not pixel width or simulator identity. Frames can explicitly retain the scene when native chrome requires it. Periscope and Developer Overlay use this option without changing their configured traits, insets, or sizing. Developer Overlay's native glass otherwise develops bright bands and a hard material cutoff. Retention can expose physical reserved regions, so general presets keep the automatic policy. Both paths restore scene and presentation state on success or failure. A nil inset override retains native geometry.
Only the captured root overrides its safe-area getter, during final pixel rendering. Native getters remain active during containment, measurement, and settling so inset changes propagate to children. Root pinning protects translated tiles. Overriding ancestors doubled asymmetric insets after measurement rehosting. Annotation padding has zero safe-area insets to avoid moving centered content. Tall tiled Year annotations retain the pre-existing limitation listed below. Regressions cover these boundaries, already-mounted inputs, compact and regular title readability, native bar stability, tiling, and failure cleanup. Full-content captures reset restored scroll offsets after readiness; viewport captures preserve them.
Accessibility subjects stay mounted during readiness and settling. Ordinary captures retain their controller parent during parsing; only upstream tiling temporarily detaches it. Annotation wrappers grow only after the final accessibility parse. Synthetic viewports recover native navigation-bar metadata synchronously, restore window geometry before parsing, and restore the original getters on every exit.
Pixel settling retains main’s normalized pixel comparison and retry policy. Final reference-comparison tolerances remain unchanged. Hosted resize, restoration, full-content, PNG export, and cancellation checks cover the shared pipeline.
Snapshot shard discovery accepts literal multiline source arrays with shared support files. Unsupported declarations fail without borrowing a following target's sources. The existing shard assignments stay unchanged.
Compatibility and review focus
Testing
At
42ab5b40e,./test --review --only SnapshotKitTests --only WhereUISnapshotTests/DeveloperOverlaySnapshotTestspassed all 56 SnapshotKit tests and the Developer Overlay image suite (all six captures matched byte for byte). Architecture and SwiftFormat passed. Review fixes preserve the existing mappings and presets; no references changed.Full gates on the current head
42ab5b40e: GitHub Actions and CircleCI pipeline 2195.At
f05ca6240, the full run passed 2,922 iOS unit tests and 28 host macro tests. All 71 snapshot tests are covered by the full run plus focused assertions after review; 679 affected WhereUI tests also passed after the eager Timeline change../test --no-generate --review --timings --only WhereUITestswith the seven affected snapshot suites verified the refreshed references. A final./test --no-generate --no-build --review --only WhereUISnapshotTests/DeveloperOverlaySnapshotTestsrepeated all six overlay captures byte for byte. Architecture checks and SwiftFormat passed.Full gates for the capture-repair baseline (before the exhaustive-conversion refactor and documentation cleanup): GitHub Actions and CircleCI pipeline 2188.
The capture fixes and reference migration are verified at this PR's own layer. A green stack tip cannot establish that an earlier PR's renderer and references agree. Layer-specific Timeline, Settings, and Year references retain the behavior present here rather than borrowing later adaptive UI semantics.
Stack
First active layer, based on main after #376 merged. This supplies the capture foundation for #378 and #372. Capture corrections and their references land here; adaptive corrections and references land with the app integration.
Backlog reconciliation
The 13 preserved Duo records are tracked in Linear. STU-318 owns adoption and its six implementation sub-issues. This slice relates to STU-319, STU-320, STU-327. Unmerged implementation remains In Review.
Remaining Backlog work: native Duo release validation (STU-316), intermittent Locations settling diagnostics (STU-317), and tall Year accessibility annotations (STU-325). Existing STU-114 and STU-252 now distinguish the partial fixes from their remaining requirements; both retain their priorities, labels, and open state.